基本语法
基本语法
python 是一个脚本语言,我们写 Python 代码实际上就是在写 Python 脚本文件,跟 Bash 脚本很像。
这跟 Java 需要定义类,在类中写代码不一样,写 Python 代码不需要定义这些东西,直接在文件的第一行就可以开始写流程处理语句了,非常简单
脚本语言,就是很轻量,python 在数据处理方面,确实有优势,好多次我用 Java 造数据的时候都感觉到很笨重,确实用 python 可能会更简单。
Python 中常用的有 6 种值(数据)的类型:
类型 | 描述 | 说明 |
---|---|---|
数字(Number) | 支持:整数(int)、浮点数(float)、复数(complex)、布尔(bool) | 整数(int),如:10、-10;浮点数(float),如:13.14、-13.14;复数(complex),如:4+3j,以 j 结尾表示复数;布尔(bool)表达现实生活中的逻辑,即真和假,True 表示真,False 表示假。True 本质上是一个数字记作 1,False 记作 0 |
字符串(String) | 描述文本的一种数据类型 | 字符串(string)由任意数量的字符组成 |
列表(List) | 有序的可变序列 | Python 中使用最频繁的数据类型,可有序记录一堆数据,长度可变,且索引对应的元素可更改,比如 [1,13,54] ,有点像 Java 中的 List |
元组(Tuple) | 有序的不可变序列 | 可有序记录一堆不可变的 Python 数据集合,长度可变,且索引对应的元素不可更改(不可更新不可删除),比如 (1,13,54) ,也就是元组一旦定义就无法更改。且只能通过拼接增加内容 |
集合(Set) | 无序不重复集合 | 可无序记录一堆不重复的 Python 数据集合,有点像 Java 中的 Set |
字典(Dictionary) | 无序 Key-Value 集合 | 可无序记录一堆 Key-Value 型的 Python 数据集合,有点像 Java 中的 Map |
字面量
包括数字和字符串。
字符串要用双引号包起来
特殊的字面量 None
Python 中有一个特殊的字面量:None
,其类型是:<class 'NoneType'>
,无返回值的函数,实际上就是返回了 None
这个字面量
None
的用处:
-
用在函数无返回值上
-
用在 if 判断上
- 在 if 判断中,None 等同于 False
-
用于声明无内容的变量上
定义变量,但暂时不需要变量有具体值,可以用 None 来代替
注释
单行注释以 #
开头,建议跟注释内容以一个空格隔开
多行注释,以一对三个引号包起来的内容
"""
多行注释
多行注释
多行注释
"""
Pycharm 中无法通过快捷点实现多行注释
变量
声明变量不需要指定类型,这个跟 Bash 有点像,在 Bash 中声明变量也是不需要声明类型的。
简单学习了 type()
方法和类型转换的 int()
、float()
、str()
方法,实践代码如下
# 声明变量不需要指定类型
# 一行语句结束了也不需要用;来结尾,这个跟JavaScript一样
wallet = 45
# print可以直接指定多个参数,在输出结果中,多个参数用空格隔开
# 45 我靠 会自动拼接的吗
print("钱包里还剩下:", wallet, '这么多钱', '我靠', '会自动拼接的吗')
# 也可以通过 + 直接拼接字符串,但是要求+两端的内容的类型必须是字符串,
# 与Java不同,python没有自动类型转换
# 所以下面这种写法是错的,因为wallet是int类型
# print("钱包里还剩下:"+wallet+"这么多钱")
# 但是如果 wallet 是一个字符串,那就可以,可以通过str()来转换
print("钱包里还剩下:"+str(wallet)+"这么多钱")
wallet -= 10
# 等效于下面的写法
wallet = wallet -10
print("钱包里还剩下:", wallet)
# 通过type方法查看变量的类型
print(type("我靠这教程也太基础了"))
print(type(wallet))
print(type("2131"))
print(type(78.12))
# 通过int方法,将变量转换为int类型
print(int("45"))
# 会自动去掉字符串两端的空格
print(int(" 45 "))
# 会截取整数部分,丢弃小数部分
print(int(56.12))
# 以下的写法都会报错
# print(int("12.12"))
# print(int("aaa"))
# 通过float方法,将变量转换为float类型
print(float("45"))
print(float(56.12))
print(float("12.12"))
# 以下的写法都会报错
# print(float("aaa"))
# 通过str方法,将变量转换为str类型
# 基本上任何内容都可以转化为字符串
print(str("45"))
print(float(56.12))
print(str("12.12"))
print(str("aaa"))
跟 Java 不同的点:
声明变量不需要指定类型
一行语句结束了也不需要用; 来结尾,这个跟 JavaScript 一样
也可以通过 + 直接拼接字符串,但是要求 + 两端的内容的类型必须是字符串,但是与 Java 不同,python 没有自动类型转换,碰到 int 类型或者 float 类型的数据,需要通过 str() 来转换成字符串,再拼接
- 通过学习后面的格式化之后我们可以直到最后通过
f"{}"
快速格式化是最方便的
print 方法可以指定多个参数拼接过程中的分割符和结尾符,比如指定分隔符为
,
,且输出后不换行(end 参数的默认值就是换行end='\n'
)print("error", "error", sep=',', end='')
标识符
在 Python 程序中,我们可以给很多东西起名字,比如:
-
变量的名字
-
方法的名字
-
类的名字
等等
这些名字,我们把它统一的称之为标识符,用来做内容的标识。
所以,标识符:是用户在编程的时候所使用的一系列名字,用于给变量、类、方法等命名。
Python 中,标识符命名的规则主要有 3 类:
-
内容限定
标识符命名中,只允许出现:英文、中文、数字、下划线(_)这四类元素。其余任何内容都不被允许。注意,不可以以数字开头,此外不推荐使用中文。
-
大小写敏感
-
不可使用关键字
Python 总共 33 个关键字,除了
False
、None
、True
是首字母大写,其他都是全小写,python 喜欢小写。False None True and as assert break class continue def del elif else except finally for from global if import in is lambda nonlocal not or pass raise return try while with yield
变量命名规范:
-
多个单词组合变量名,要使用下划线做分隔。
-
命名变量中的英文字母,应全部小写
在 Java 中,标识符的命名规范是驼峰命名,但是在 Python 中,一般不使用驼峰命名(camel case),而是使用下划线分隔单词同时单词全小写的风格(snake case)。
在 IDEA 的
StringManipulation
插件可以很方便的进行格式切换
运算符
包含四则运算和取整取余等运算符
运算符 | 描述 | 例子 |
---|---|---|
+ | 加 | 两个对象相加 a + b 输出结果 30 |
- | 减 | 得到负数或是一个数减去另一个数 a - b 输出结果 -10 |
* | 乘 | 两个数相乘或是返回一个被重复若干次的字符串 a * b 输出结果 200 |
/ | 除 | b / a 输出结果 2 |
// | 取整数 | 返回商的整数部分 9//2 输出结果 4 , 9.0//2.0 输出结果 4.0 |
% | 取余数 | 返回除法的余数 b % a 输出结果 0 |
** | 指数 | a**b 为 10 的 20 次方, 输出结果 100000000000000000000 |
简单实践一下
num = 10 + 20
divide = 11
a = num / divide
print(a)
# 整形取整
a = num // divide
print(a)
# 就算是float,用 // 也能得到一个整数结果
a = 20.12 // divide
print(a)
a = num % divide
print(a)
# 指数运算符,在Java中是没有了,Java只能通过函数实现指数运算
a = 10 ** 3
print(a)
输出
2.727272727272727
2
1.0
8
1000
跟 Java 对比一下区别:
/
:在 Java 中,整形在使用/
的时候是取整操作,float 或者 double 类型进行/
运算的时候,才是除。Java 中没有直接用于指数计算的运算符,只能通过函数来支持,比如
Math.pow(10, 3)
运算符还可以跟 =
组合,简化代码编写
运算符 | 描述 | 例子 |
---|---|---|
+= | 加法赋值运算符 | c += a 等效于 c = c + a |
-= | 减法赋值运算符 | c -= a 等效于 c = c - a |
*= | 乘法赋值运算符 | c *= a 等效于 c = c * a |
/= | 除法赋值运算符 | c /= a 等效于 c = c / a |
//= | 取整除赋值运算符 | c //= a 等效于 c = c // a |
%= | 取模赋值运算符 | c %= a 等效于 c = c % a |
**= | 幂赋值运算符 | c **= a 等效于 c = c ** a |
简单实践
# 赋值运算符
c = 100
c += 5
print(c)
c -= 10
print(c)
c /= 2
print(c)
c //= 3
print(c)
c %= 10
print(c)
c **= 2
print(c)
输出
105
95
47.5
15.0
5.0
25.0
运算符的优先级
参考文档:Python运算符优先级和结合性一览表
运算符说明 | Python 运算符 | 优先级 | 结合性 |
---|---|---|---|
小括号 | ( ) | 19 | 无 |
索引运算符 | x[i] 或 x[i1:i2[:i3]] | 18 | 左 |
属性访问 | x.attribute | 17 | 左 |
乘方 | ** | 16 | 右 |
按位取反 | ~ | 15 | 右 |
符号运算符 | +(正号)、-(负号) | 14 | 右 |
乘除 | *、/、//、% | 13 | 左 |
加减 | +、- | 12 | 左 |
位移 | >>、<< | 11 | 左 |
按位与 | & | 10 | 右 |
按位异或 | ^ | 9 | 左 |
按位或 | | | 8 | 左 |
比较运算符 | ==、!=、>、>=、<、<= | 7 | 左 |
is 运算符 | is、is not | 6 | 左 |
in 运算符 | in、not in | 5 | 左 |
逻辑非 | not | 4 | 右 |
逻辑与 | and | 3 | 左 |
逻辑或 | or | 2 | 左 |
逗号运算符 | exp1, exp2 | 1 | 左 |
优先级越高,越优先计算,同优先级的运算符一起出现的时候,考虑运算符的结合性,先执行左边的叫左结合性,先执行右边的叫右结合性。
例如对于表达式对于 100 / 25 * 16
,/
和 *
的优先级相同,应该先执行哪一个呢?这个时候就不能只依赖运算符优先级决定了,还要参考运算符的结合性。/
和 *
都具有左结合性,因此先执行左边的除法,再执行右边的乘法,最终结果是 64。
Python 中大部分运算符都具有左结合性,也就是从左到右执行;只有 **
乘方运算符、单目运算符(例如 not 逻辑非运算符)、赋值运算符和三目运算符例外,它们具有右结合性,也就是从右向左执行。上表中列出了所有 Python 运算符的结合性。
虽然 Python 运算符存在优先级的关系,但我不推荐过度依赖运算符的优先级,这会导致程序的可读性降低。因此,我建议读者:
- 不要把一个表达式写得过于复杂,如果一个表达式过于复杂,可以尝试把它拆分来书写。
- 不要过多地依赖运算符的优先级来控制表达式的执行顺序,这样可读性太差,应尽量使用
( )
来控制表达式的执行顺序。
简单实践一下:
# 运算符的优先级
# 先计算指数,再乘以10
num = 10*12**3
print(num)
输出
17280
字符串
参考文档:Python 字符串 | 菜鸟教程
注意,不要将文件名命名为
string.py
,因为 Python 的官方库中已经有一个string.py
文件了,比如Python3.10.4\Lib\string
定义
字符串在 Python 中有多种定义形式:
-
单引号定义法:
name='tom'
-
双引号定义法:
name="tom"
-
三个双引号定义法::
name="""tom"""
- 三个双引号定义法,和多行注释的写法一样,同样支持换行操作。区别就是:使用变量接收它,它就是字符串。不使用变量接收它,就可以作为多行注释使用
如果字符串的内容中包含 '
或者 "
怎么办?可以使用转移字符 \
来将引号解除效用,变成普通字符串
简答实践如下:
name = 'tom'
print(type(name))
print(name)
name = "tom"
print(name)
name = """
i am tom
i like coding
"""
print(name)
# 转义字符的使用
name = '\'tom\''
print(name)
name = "\"tom\""
print(name)
name = """"
"tset"
i am tom
i like coding
\""""
print(name)
# 不进行转义,直接输出字符串原本的内容
name_raw = r'\'tom\''
# 输出 \'tom\'
print(name_raw)
输出
<class 'str'>
tom
tom
i am tom
i like coding
'tom'
"tom"
"
"tset"
i am tom
i like coding
"
\'tom\'
交互式 Python shell 中,输入 """
再回车,可进行多行输入,不需要专门在行末添加使用续行符 \
>>> name="""
... fasdfa
... dfasd
... dfasda
... """
>>> print(name)
fasdfa
dfasd
dfasda
>>>
拼接
这个其实很简单,可以直接通过 + 来将字符串类型的变量进行拼接,不过要注意,+ 无法将字符串类型和非字符串类型的变量拼接,我们可以将其他变量通过 str() 来转换成字符串,再拼接
这一点在
变量
小节已经讨论过
这个问题我们可以通过字符串格式化解决
字符串格式化
方式有三种:
假设 a1,a2 为待格式化的数字
-
"%s,%d" % (a1,a2)
我们可以使用辅助符号
m.n
来控制数据的宽度和精度-
m
,控制宽度,要求是数字(很少使用),设置的宽度小于数字自身时,不生效 -
.n
,控制小数点精度,要求是数字,会进行小数的四舍五入
示例:
-
%5d
:表示将整数的宽度控制在 5 位,如数字 11,被设置为 5d,就会变成:[空格][空格][空格]11,用三个空格补足宽度。 -
%5.2f
:表示将宽度控制为 5,将小数点精度设置为 2小数点和小数部分也算入宽度计算。如,对 11.345 设置了%7.2f 后,结果是:[空格][空格]11.35。2 个空格补足宽度,小数部分限制 2 位精度后,四舍五入为 .35
-
%.2f
:表示不限制宽度,只设置小数点精度为 2,如 11.345 设置%.2f 后,结果是 11.35 -
%05d
:右对齐,不足左边补 0 -
%-5d
:-
代表左对齐,不足右边默认补空格 -
%-05d
:-
代表左对齐,左对齐时设置补 0 是无效的,因为往右边补 0 会改变数字的大小
-
-
字符串的 format 方法
"{},{}".format(a1,a2)
非常灵活,推荐使用Python2.6 开始,新增了一种格式化字符串的函数
str.format()
,它增强了字符串格式化的功能。基本语法是通过{}
和 : 来代替以前的%
。format
函数可以接受不限个参数,位置可以不按顺序。{indexOrName:*<5}
:index 指定参数的索引或者名称,或者可以不写,按照参数顺序自动对应,*
表示填充元素,默认为空格,<
为填充格式,对齐方式有>
:右对齐、<
:左对齐、^
:中间对齐,5 表示输出长度-
数字 格式 输出 描述 3.1415926 3.14 保留小数点后两位 3.1415926 +3.14 带符号保留小数点后两位 -1 -1.00 带符号保留小数点后两位 2.71828 3 不带小数 5 05 数字补零 (填充左边, 宽度为 2) 5 5xxx 数字补 x (填充右边, 宽度为 4) 10 10xx 数字补 x (填充右边, 宽度为 4) 1000000 1,000,000 以逗号分隔的数字格式 0.25 25.00% 百分比格式 1000000000 1.00e+09 指数记法 13 13 右对齐 (默认, 宽度为 10) 13 13 左对齐 (宽度为 10) 13 13 中间对齐 (宽度为 10)
-
-
快速格式化
f''
,python3.6 后的版本支持f'{a1},{a2}'
,特点是不关注类型,不做精度控制,原样输出,适合对精度没有要求的快速格式化的需求,常用- 注意不一定非用单引号,用双引号或者三引号都可以。
简单实践如下:
# 1、 " %s,%d " % (a1,a2)
print("my name is %s, my height is %.2f cm" % ("xiaohong", 2.345))
''' %s : 字符串
%d :十进制整数
%f : 浮点型, %.3f: 保留三位小数
%x : 十六进制
指定长度:
%5d 右对齐,不足左边补空格
%05d 右对齐,不足左边补0
%-5d - 代表左对齐,不足右边默认补空格
%-05d - 代表左对齐,左对齐时设置补0是无效的,因为往右边补0会改变数字的大小
浮点数:
%f 默认是输出6位有效数据, 会进行四舍五入
%.2f 指定小数点位数的输出 保留小数点后2位,会进行四舍五入
%6.4f 6代表整个浮点数的长度,包括小数点和小数部分,只有当字符串的长度小于6位才起作用,不足6位空格补足,可以用%04.8使用0补足空格,默认左边补0(右对齐),
可以通过 - 设置左对齐,左对齐时设置补0是无效的
'''
age =18
name= "xiashuo.xyz"
salary=45.1265
# % 表示:我要占位
# s 表示:将变量转化成字符串类型放入占位的地方
introduction = "my name is %s , and i am %s years old , my salary is %s" % (name, age, salary)
print(introduction)
print('------------------------------------------------')
# 除了%s 还可以使用别的类型 比如 %d 、 %f 同时浮点型保留四位小数
introduction = "my name is %s\nand i am %05d years old\nmy salary is %08.3f" % (name, age, salary)
# 45.1265 被格式化为 0045.127 7是保留三位小数同时四舍五入来的,同时前面两个0是为了补齐8位
print(introduction)
print('------------------------------------------------')
# 2、'{1},{2}'.format(a1,a2)
# 1) 顺序填坑:{} 占位符
print('姓名是 {},年龄是 {}'.format('Tom', 20))
# 2) 下标填坑
print('姓名是 {0},年龄是 {1}'.format('Tom', 20))
# 3) 变量填坑
print('姓名是 {name},年龄是 {age}'.format(name='Tom', age=20))
print('------------------------------------------------')
# 4)对齐方式
# {:5} 指定输出长度为5. 该方式下字符串和数字的对齐形式是不一致的。字符串是左对齐,数字是右对齐。
# 用> < ^ 可以避免字符串/数值对齐方法不一致
'''
输出 不使用指定长度对齐
姓名是:Tom
年龄是:20
'''
print('姓名是:{0}\n年龄是:{1}'.format('Tom', 20))
print('------------------------------------------------')
'''
输出 使用{:5}指定长度
字符串和数字的对齐形式是不一致的。字符串是左对齐,数字是右对齐。
姓名是:Tom
年龄是: 20
'''
print('姓名是:{0:5}\n年龄是:{1:5}'.format('Tom', 20))
print('------------------------------------------------')
'''
输出 使用右对齐 >
姓名是: Tom
年龄是: 20
'''
print('姓名是:{0:>5}\n年龄是:{1:>5}'.format('Tom', 20))
print('------------------------------------------------')
'''
输出 使用左对齐 <
姓名是:Tom
年龄是:20
'''
print('姓名是:{0:<5}\n年龄是:{1:<5}'.format('Tom', 20))
print('------------------------------------------------')
'''
输出 使用中间对齐^
姓名是: Tom
年龄是: 20
'''
print('姓名是:{0:^5}\n年龄是:{1:^5}'.format('Tom', 20))
print('------------------------------------------------')
'''
输出 使用中间对齐^,指定填充字符为*
姓名是:*Tom*
年龄是:*20**
'''
print('姓名是:{0:*^5}\n年龄是:{1:*^5}'.format('Tom', 20))
print('------------------------------------------------')
'''
指定浮点数精度
输出 使用中间对齐^,指定填充字符为*
姓名是:*Tom*
年龄是:*20.13**
'''
print('姓名是:{0:*^5}\n年龄是:{1:*^8.2f}'.format('Tom', 20.129))
print('------------------------------------------------')
# 3、f'{a1},{a2}'
# python3.6 后的版本支持 特点是不关注类型,不做精度控制,原样输出
name = 'Tom'
age = 20
# 直接使用上下文中的变量
print(f'姓名是:{name},年龄是:{age}')
print('------------------------------------------------')
# 甚至可以不写变量
print(f'姓名是:{"梁康"},年龄是:{12.12}')
print('------------------------------------------------')
#
print(f"姓名是:{'我靠,真牛逼'},年龄是:{12.12}")
print('------------------------------------------------')
#
print(f"""
我的的名字是虾说
其实我的真实姓名时{name}
我的年龄时{age}
这些都不重要
重要的是我一定会成为一个{"niubi"}的人,numer {1}
""")
输出
my name is xiaohong, my height is 2.35 cm
my name is xiashuo.xyz , and i am 18 years old , my salary is 45.1265
------------------------------------------------
my name is xiashuo.xyz
and i am 00018 years old
my salary is 0045.127
------------------------------------------------
姓名是 Tom,年龄是 20
姓名是 Tom,年龄是 20
姓名是 Tom,年龄是 20
------------------------------------------------
姓名是:Tom
年龄是:20
------------------------------------------------
姓名是:Tom
年龄是: 20
------------------------------------------------
姓名是: Tom
年龄是: 20
------------------------------------------------
姓名是:Tom
年龄是:20
------------------------------------------------
姓名是: Tom
年龄是: 20
------------------------------------------------
姓名是:*Tom*
年龄是:*20**
------------------------------------------------
姓名是:*Tom*
年龄是:*20.13**
------------------------------------------------
姓名是:Tom,年龄是:20
------------------------------------------------
姓名是:梁康,年龄是:12.12
------------------------------------------------
姓名是:我靠,真牛逼,年龄是:12.12
------------------------------------------------
我的的名字是虾说
其实我的真实姓名时Tom
我的年龄时20
这些都不重要
重要的是我一定会成为一个niubi的人,numer 1
转义字符
转义字符 | 描述 | 实例 |
---|---|---|
\ (在行尾时) |
续行符 | >>> print("line1 \ ... line2 \ ... line3") line1 line2 line3 >>> |
\\ |
反斜杠符号 | >>> print("\") \ |
\' |
单引号 | >>> print(''') ' |
\" |
双引号 | >>> print(""") " |
\a |
响铃 | >>> print("\a") 执行后电脑有响声。 |
\b |
退格 (Backspace) | >>> print("Hello \b World!") Hello World! |
\000 |
空 | >>> print("\000") >>> |
\n |
换行 | >>> print("\n") >>> |
\v |
纵向制表符 | >>> print("Hello \v World!") Hello World! >>> |
\t |
横向制表符 | >>> print("Hello \t World!") Hello World! >>> |
\r |
回车,将 \r 后面的内容移到字符串开头,并逐一替换开头部分的字符,直至将 \r 后面的内容完全替换完成。 |
>>> print("Hello\rWorld!") World! >>> print('google runoob taobao\r123456') 123456 runoob taobao |
\f |
换页 | >>> print("Hello \f World!") Hello World! >>> |
\yyy |
八进制数,y 代表 0~7 的字符,例如:\012 代表换行。 | >>> print("\110\145\154\154\157\40\127\157\162\154\144\41") Hello World! |
\xyy |
十六进制数,以 \x 开头,y 代表的字符,例如:\x0a 代表换行 | >>> print("\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21") Hello World! |
\other |
其它的字符以普通格式输出 |
\r
的一个作用是实现百分比进度:
import time
for i in range(101):
print("\r{:3}%".format(i), end=' ')
# 线程暂停 0.1 s
time.sleep(0.1)
输出结果从 1%
,刷新到 100%
,很有意思,哈哈哈:
56%
通过,在字符串前面加上 r
或者 R
来取消转移,比如
# 不进行转义,直接输出字符串原本的内容
name_raw = r'\'tom\''
# 输出 \'tom\'
print(name_raw)
不可打印字符
这些不可打印字符都是转义字符,具体请看
转义字符
小节
8 个不可打印字符 \cx
,\f
,\n
,\r
,\s
,\S
,\t
、\v
-
\cx
匹配由 x 指明的控制字符,x 值必需为 A-Z 或 a-z 的大小写字符,\cA 匹配一个 Control-A 控制字符 -
\f
匹配一个换页符,leaf -
\n
匹配一个换行符,next -
\r
匹配一个回车符,enter -
\t
匹配一个制表符,table -
\v
匹配一个垂直制表符,vertical -
\s
匹配任何空白字符,等效于 [\r\n\r\t\v] -
\S
匹配任何非空白字符
字符串的相关方法
简单实践
str_now = "abcdefg13456"
print("------------------------------字符串中的内部函数----------------------------------")
print("----大小写相关----")
# 首字母大写
print(str_now.capitalize())
# 返回一个不大小写不敏感的字符串用于对比
# 效果跟 lower 有点像
print("ABcdEFG123456".casefold())
# 全大写
# 输出 ABCDEFG
print("abcdefg".upper())
# 全小写
# 输出 abcdefg
print("ABCDEFG".lower())
# 大小写反转
# 输出 abCDEfg
print("ABcdeFG".swapcase())
# 将每一个单词的首字母大写,每一个单词除首字母以外的字母小写,
# 这个叫title case 还挺有意思的
print("this is my life".title())
print("tHis iS mY liFe".title())
print("----格式化相关----")
# 格式化,我们前面已经了解过了
print('姓名是 {name},年龄是 {age}'.format(name='Tom', age=20))
# 参数类型必须是字典,没有format方法灵活
print("myname is {name}".format_map({"name": "xiashuo"}))
# 在字符串左边补零,将字符串补足到指定长度
print("python".zfill(15))
# 居中对齐
# 将字符串内容放到指定长度的中间,可以指定左右填充字符,默认使用空格
# 输出" python "
print("python".center(10))
# 输出"**python**"
print("python".center(10, "*"))
# 左对齐
print("python".ljust(10, "*"))
# 右对齐
print("python".rjust(10, "*"))
# tab 符号 \t 默认的列宽是8个字符,如果一列的内容宽度不到8,会用空格补齐,如果超过了一倍的列宽,那就会按照两倍的列宽补齐空格,以此类推
# 默认列宽8个字符
# 输出
# python Java C++
# python1 Java1 C++1
print("python\tJava\tC++\npython1\tJava1\tC++1".expandtabs())
# 我们可以指定列宽为任意个字符
# python Java C++
# python1 Java1 C++1
print("python\tJava\tC++\npython1\tJava1\tC++1".expandtabs(12))
print("----编码/解码----")
# 字符串的编解码
str_encode = "我的天空".encode(encoding="utf-8", errors="strict")
print(str_encode)
str_decode = str_encode.decode(encoding="utf-8", errors="strict")
print(str_decode)
print("----前缀/后缀的处理----")
# 是否以字符串开头
print("abcdefg".startswith("abc"))
# 可以指定匹配的多个字符串,用元组传入
print("abcdefg".startswith(("1", "abc")))
# 可以指定起点和终点索引
print("0123abcdefg".startswith(("123", "abc"), 1, 6))
# 长度不够,导致匹配不到
print("0123abcdefg".startswith(("123", "abc"), 1, 3))
# 是否以字符串结束
print("abcdefg".endswith("efg"))
# 可以指定匹配的多个字符串,用元组传入
print("abcdefg".endswith(("1", "efg")))
# 可以指定起点和终点索引
print("abcdefg01230".endswith(("123", "abc"), -6, -1))
# 长度不够,导致匹配不到
print("0123abcdefg".endswith(("123", "abc"), -2, -1))
# 删除字符串头尾的指定字符,即,删除指定前缀后缀,如果不指定,那就是删除空格,包括换行符
python_str = " python \n"
strip_result = python_str.strip()
# 注意,原字符串是不会变化的,返回的是出来之后的结果
print(python_str)
print("去掉前缀后缀:"+strip_result)
# 如果指定了字符串,会按照指定字符串中的所有字符来删除前缀后缀
# 输出 ython 字符串头部的 aaap 和尾部的 bbb 被删除
print("aaapythonbbb".strip("abp"))
# 只删除前缀
# 输出 ythonaa
print("aaapythonaa".lstrip("abpn"))
# 只删除后缀
# 输出 aaapytho
print("aaapythonaa".rstrip("abpn"))
# 移除前缀,效果类似于 string[len(prefix):] 效果等同于 lstrip
print("aaa_python".removeprefix("aa"))
# 移除后缀 效果等同于 rstrip
print("python_bbb".removesuffix("bb"))
print("----拼接----")
# 分隔符调用join,join方法的参数是列表或者字典或者元组或者集合
print("&&".join(["a", "b", "c", "d"]))
print("&&".join(("a", "b", "c", "d")))
print("&&".join({"a", "b", "c", "d"}))
print("&&".join({"a": "1", "b": "2", "c": "3", "d": "4"}))
# 输出都是a&&b&&c&&d
print("----翻译(替换)----")
# 如果只有一个参数,它必须是一个将Unicode序数(整数)或字符映射为Unicode序数、字符串或None的字典。然后将字符键转换为序号。
# 如果有两个参数,它们必须是长度相等的字符串,那样在结果字典中,x中的每个字符将被映射到y中相同位置的字符。如果有第三个参数,它必须是一个字符串,其字符将被映射到结果中的None。
# table_1 和 table_2 的效果相同
table_1 = str().maketrans({"t": "1", "h": "2", "i": "3", "s": "4", ".": None, "p": None, "y": None})
# 一般我们用这种方式,比较方便
table_2 = str().maketrans("this", "1234", ".py")
print(table_1)
print(table_2)
str_2_trans = "this is string example....wow!!! py"
# translate 方法处理的是原字符串的副本,并不会修改源字符串
print(str_2_trans.translate(table_1))
print(str_2_trans.translate(table_2))
# 源字符串没有修改
# replace 替换方法,不支持正则表达式
# 移除字符串中的空格
print("p y t h o n".replace(" ", ""))
# 只替换头两个"aa",再有多的也不管了
print("pyaataahaaobbn".replace("aa", "", 2))
# 好像没有从右边开始替换的方法,那我们就自己实现一个
def right_replace(string, old, new, max=1):
return string[::-1].replace-1], new[::-1], max[::-1]
print(right_replace("pyaataahaaobbn", "aa", "", 2))
print("----分割(小段分割)----")
# 传入分隔符,将字符串分为三部分,分隔符之前的部分、分隔符自身、分隔符后面的部分,用这三个部分按顺序组成元组返回
# 如果没找到分隔符,返回的元组的第一个元素就是字符串本身,然后后面两个字符串都是空
# 注意,如果字符串中存在多个分隔符,只会按照第一个分隔符所在的位置分割,忽略后续的分隔符,
# 即 partition 最终的结果,一定是一个包含三个字符串元素的元组
# 返回('py', 'th', 'on')
print("python".partition("th"))
# 返回('python', '', '')
print("python".partition("ths"))
# 注意,如果字符串中存在多个分隔符,只会按照第一个分隔符所在的位置分割,忽略后续的分隔符,
# 返回('1111', ';', '2222;3333;4444')
print("1111;2222;3333;4444".partition(";"))
# 当然,我们也可以从右边开始找分隔符,找到之后以其为分割点做分割
# 返回('1111;2222;3333', ';', '4444')
print("1111;2222;3333;4444".rpartition(";"))
# 通过分隔符将字符串分割为多份,
# 第一个参数是分隔符,如果不设置,也就是None,那就会以空格或者空白进行分割,包括\\n \\r \\t \\f 这些转义字符,同时如果分割出的部分是空字符串,则会将其丢弃,最终的效果就像是分隔符好像是任意宽度的空格
# 第二个参数是最大分割次数(从左边开始)。-1(默认值)表示没有限制。0表示不分割,直接返回整个字符串,1表示分割一次,字符串被分割为两段,返回的结果列表的最大索引是1,2表示分割两次,字符串被分割为三段,返回的结果列表的最大索引是2,以此类推
print("111 222 333 444 555".split())
# 最终的效果就像是分隔符好像是任意宽度的空格
print("111 222 333 444 555".split())
print("111 \t 222 \t333 \t444\t555".split())
# 返回['1', '2', '3', '4', '5', '6', '7', '8', '9']
print("1;2;3;4;5;6;7;8;9".split(";"))
# 返回['1', '2', '3', '4', '5', '6', '7', '8;9']
print("1;2;3;4;5;6;7;8;9".split(";", 7))
# 当然,我们也可以从右边开始分割
# 返回['1;2', '3', '4', '5', '6', '7', '8', '9']
print("1;2;3;4;5;6;7;8;9".rsplit(";", 7))
# 按照换行来拆分字符串 只要是能换行符号的都会被采纳为分隔符
str_multiple_line = """aaa
bbb
ccc
ddd
eee
ffff
"""
# 输出['aaa', 'bbb', 'ccc', 'ddd', 'eee', 'ffff']
print('"""', str_multiple_line.splitlines())
# \n 会被拆分
str_multiple_line_3 = "1111\n222\n333"
print("\\n", str_multiple_line_3.splitlines())
# \f 会被拆分
str_multiple_line_3 = "1111\f222\f333"
print("\\f", str_multiple_line_3.splitlines())
# \v 会被拆分
str_multiple_line_3 = "1111\v222\v333"
print("\\v", str_multiple_line_3.splitlines())
# 如果参数为True,会把分隔符也带在后面
str_multiple_line_4 = "1111\n222\n333"
print("\\n with delimiter", str_multiple_line_4.splitlines(True))
print("----统计相关----")
str_temp = "aaa124556aaa123aaa"
# 在指定的范围内查找特定字符串出现的次数
# 不指定范围的话就是全部字符
print(str_temp.count("aaa"))
print(str_temp.count("123"))
# 指定范围为 0-9
print(str_temp.count("aaa", 0, 9))
print("----查找相关----")
# 查询指定字符串在特定范围内第一次出现的位置
# 不指定范围的话就是全部字符
# 没找到就报错
print(str_temp.index("12"))
print(str_temp.index("12", 10, 19))
# ValueError: substring not found
# print(str_temp.index("1#"))
# 查询指定字符串在特定范围内最后一次出现的位置
# 不指定范围的话就是全部字符
print(str_temp.rindex("aaa"))
# 跟 index 方法功能完全相同,
# 唯一的区别就是 index方法找不到的时候直接报错,find犯法找不到的时候返回 -1,
print(str_temp.find("12"))
print(str_temp.find("12", 10, 19))
print(str_temp.rfind("aaa"))
print("----判断相关----")
# 是否是字母和数字组成的字符串
print("12fd".isalnum())
print("12fd@@".isalnum())
# 是否每个字符都是字母或者中文字符
print("dfasdfa".isalpha())
print("dfasdfa121".isalpha())
# 中文字符 isalpha 返回true
print("中文字符", "中文字符".isalpha())
# 是否字符串中的字符都是数字
# 注意要跟能否转化为数字进行区分
print("121".isnumeric())
# 小数会返回False,因为 . 不是数字
print("121.2".isnumeric())
print("dfasdfa".isnumeric())
# 是否每个字符都是 ascii 字符
# 键盘上能敲出来的特殊符号都是 ascii 字符
print("+/!@#".isascii())
# 26个英文字母也是 ascii 字符
print("abcdefg".isascii())
# 但是汉字不是ascii 字符,中文输入法下的符号比如!,也不是ascii 字符,其它语言的文字也不是
print("我¥!".isascii())
# 关于什么是ascii 字符,请看 http://c.biancheng.net/c/ascii/ 中的表格的 字符/缩写 这一列
# 是否每个字符都是 数字 ,跟 isnumeric 好像没有区别
print("123456".isdigit())
# . 不是数字
print("123.456".isdigit())
print("ADCD".isdigit())
# 是否每个字符都是 十进制 数字 ,跟 isnumeric 好像没有区别
print("1213".isdecimal())
# 0x 都是16进制字符
print("0x1213", "0x1213".isdecimal())
# 字符串是关键字
print("def".isidentifier())
print("class".isidentifier())
# 1213不是关键字
print("1213".isidentifier())
# 是否每个字符都是 小写
print("dfasdfa".islower())
print("DFASDFA".islower())
# 是否每个字符都是 大写
print("DFASDFA".isupper())
print("dfasdfa".isupper())
# 是否每个字符都是 空格
print(" ".isspace())
print(" ".isspace())
# 基本上这些转义字符都是空格
print("\t".isspace())
print("\f".isspace())
print("\n".isspace())
print("\f".isspace())
print("\r".isspace())
"""
8个不可打印字符\cx,\f,\n,\r,\s,\S,\t、\v
\cx匹配由x指明的控制字符,x值必需为A-Z或a-z的大小写字符,\cA匹配一个Control-A控制字符
\f匹配一个换页符,leaf
\n匹配一个换行符,next
\r匹配一个回车符,enter
\t匹配一个制表符,table
\v匹配一个垂直制表符,vertical
\s匹配任何空白字符,等效于[\r\n\r\t\v]
\S匹配任何非空白字符
"""
# 是否所有的字符都是可打印的
print("dfasdfasd".isprintable())
print("12\n".isprintable())
# 所有单词都是以大写开始,其余字母均为小写
print("This Is My Life".istitle())
print("this is my life".istitle())
输出日志:
------------------------------字符串中的内部函数----------------------------------
----大小写相关----
Abcdefg13456
abcdefg123456
ABCDEFG
abcdefg
abCDEfg
This Is My Life
This Is My Life
----格式化相关----
姓名是 Tom,年龄是 20
myname is xiashuo
000000000python
python
**python**
python****
****python
python Java C++
python1 Java1 C++1
python Java C++
python1 Java1 C++1
----编码/解码----
b'\xe6\x88\x91\xe7\x9a\x84\xe5\xa4\xa9\xe7\xa9\xba'
我的天空
----前缀/后缀的处理----
True
True
True
False
True
True
True
False
python
去掉前缀后缀:python
ython
ythonaa
aaapytho
a_python
python_b
----拼接----
a&&b&&c&&d
a&&b&&c&&d
a&&c&&b&&d
a&&b&&c&&d
----翻译(替换)----
{116: '1', 104: '2', 105: '3', 115: '4', 46: None, 112: None, 121: None}
{116: 49, 104: 50, 105: 51, 115: 52, 46: None, 112: None, 121: None}
1234 34 41r3ng examlewow!!!
1234 34 41r3ng examlewow!!!
python
pythaaobbn
pyaathobbn
----分割(小段分割)----
('py', 'th', 'on')
('python', '', '')
('1111', ';', '2222;3333;4444')
('1111;2222;3333', ';', '4444')
['111', '222', '333', '444', '555']
['111', '222', '333', '444', '555']
['111', '222', '333', '444', '555']
['1', '2', '3', '4', '5', '6', '7', '8', '9']
['1', '2', '3', '4', '5', '6', '7', '8;9']
['1;2', '3', '4', '5', '6', '7', '8', '9']
""" ['aaa', 'bbb', 'ccc', 'ddd', 'eee', 'ffff']
\n ['1111', '222', '333']
\f ['1111', '222', '333']
\v ['1111', '222', '333']
\n with delimiter ['1111\n', '222\n', '333']
----统计相关----
3
1
1
----查找相关----
3
12
15
3
12
15
----判断相关----
True
False
True
False
中文字符 True
True
False
False
True
True
False
True
False
False
True
0x1213 False
True
True
False
True
False
True
False
True
True
True
True
True
True
True
True
False
True
False
Process finished with exit code 0
字符串的编码
官方文档:Unicode 指南 — Python 3.10.11 文档
Python 默认采用 UTF-8 编码,Java 和 JavaScript 默认采用 UTF-16 编码,注意区别
Python 中的字符串采用 Unicode 编码
这一点跟 Java 一样
字符的比较也是通过比较每一个字符的 Unicode 编码来实现,
字符串是按位比较,也就是一位位进行对比,只要有一位大,那么整体就大
简单实践:
屌字的 unicode 码,实际上,你可以把这个认同为这就是一个汉字:
'\u' 是转义字符,表示 unicode 编码。
char = "\u5c4c"
# 可直接输出Unicode编码对应的字符
print(char)
输出:
屌
屌字对应的 Unicode 编码对应的字符串是 \\u5c4c
,注意,这跟前面说的 Unicode 编码是不一样的,我们可以通过以下两步获取其对应的字符
char_code_str = "\\u5c4c"
print(char_code_str)
# 首先将这个字符串进行"utf-8"编码为字节
char_byte = char_code_str.encode("utf-8")
print(char_byte, type(char_byte))
# 然后再进行Unicode解码
char_new = char_byte.decode('unicode_escape')
print(char_new, type(char_new))
输出:
\u5c4c
b'\\u5c4c' <class 'bytes'>
屌 <class 'str'>
这个过程我们也可以反向来进行,获取指定字符的 Unicode 编码字符串:
print("屌".encode("unicode_escape").decode("utf-8"))
# 输出 A, 没有 Unicode码,其采用的是 ASCII 值为 0x39
print("z".encode("unicode_escape").decode("utf-8"))
# 输出 9, 没有 Unicode码,其采用的是 ASCII 值为 0x7A
print("9".encode("unicode_escape").decode("utf-8"))
输出:
\u5c4c
z
9
现在我们开始字符串的比较
数字和字符 均采用 ASCII 编码,跟中文的比较也是直接拿 ASCII 码跟 Unicode 码比较,所以数字永远比汉字要小
# True
print("9" < "掉")
# True
print("z" < "掉")
汉字之间可以通过 Unicode 编码来比较:
# \u6211
print("我".encode("unicode_escape").decode("utf-8"))
# \u7684
print("的".encode("unicode_escape").decode("utf-8"))
# True
print("我" < "的")
相同字符串的比较
这个 Java 有所不同,
第一个比较:Java 中 JVM 会自动复用字符串对象,返回 True
第二个比较:Java 中属于 new 了一个新对象,会返回 false,但是 Python 中不存在内存地址的比较,只会比较 Unicode 编码,所以依然为 true
# True
print("我" == "我")
# True
print("我" == str("我"))
多位比较
按位比较,也就是一位位进行对比,只要有一位大,那么整体就大
# True
print("ab" > "aaaa")
从容器视角看字符串
具体请看《数据容器.md》的
字符串(str)
小节
数字
列表
具体请看《数据容器.md》的
列表(list)
小节
元组
具体请看《数据容器.md》的
元组(tuple)
小节
集合
具体请看《数据容器.md》的
集合(set)
小节
字典
具体请看《数据容器.md》的
字典(dict)
小节
数据输入
其实就是 input
方法的应用,简单实践如下:
print("please input your name")
# 会一直阻塞,直到用户在控制台输入并回车
# 用户输入的内容时绿色的
name = input("name:")
# 用户的输入最终都是字符串类型
# 输出 <class 'str'>
print(type(name))
# 回车之后继续往后执行
print(f"your name is {name}")